package com.admin.interfaces.intercept;

import com.admin.conts.SessionKeys;
import com.admin.domain.modle.Member;
import com.admin.domain.service.WeChatMemberService;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.mp.WeixinProxy;
import com.foxinmy.weixin4j.mp.model.OauthToken;
import com.foxinmy.weixin4j.mp.model.User;
import com.foxinmy.weixin4j.util.StringUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.Date;

/**
 * 微信Oauth授权拦截
 *
 * @author jy
 * @className OauthInterceptor
 * @date 2015年10月24日
 * @see
 * @since JDK 1.7
 */
@Component
public class OauthInterceptor extends HandlerInterceptorAdapter {

    @Autowired
    private WeChatMemberService memberService;
    @Autowired
    private WeixinProxy weixinProxy;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        HttpSession session = request.getSession();
        if (session.getAttribute(SessionKeys.OAUTH_USER_KEY) == null) {
            String code = request.getParameter("code");
            if (StringUtil.isBlank(code)) {
                String accept = request.getHeader("Accept");
                if (StringUtils.hasText(accept) && accept.contains("application/json")) {
                    response.setCharacterEncoding("UTF-8");
                    response.setHeader("Content-type", "application/json;charset=UTF-8");
                    response.getWriter().write("{\"code\":-1,\"msg\":\"登陆超时，请刷新页面。\"}");
                    response.getWriter().flush();
                } else {
                    response.sendRedirect(weixinProxy.getOauthApi().getUserAuthorizationURL(getAccessUri(request),
                            "state", "snsapi_base"));
                }
                return false;
            } else {
                OauthToken oToken = null;
                User user = null;
                try {
                    oToken = weixinProxy.getOauthApi().getAuthorizationToken(code);
                    user = weixinProxy.getUser(oToken.getOpenId());
                } catch (WeixinException e) {
                    if (e.getErrorCode().equals("40029") || e.getErrorCode().equals("40163")) { // invalid
                                                                                                // code
                        response.sendRedirect(
                                weixinProxy.getOauthApi()
                                        .getUserAuthorizationURL(String.format("%s://%s%s", request.getScheme(),
                                                request.getServerName(), request.getRequestURI()), "state",
                                                "snsapi_base"));
                        return false;
                    } else if (e.getErrorCode().equals("40001")) { // invalid
                        // token
                        // 刷新token
                        weixinProxy.getTokenManager().refreshCache();
                        // 重新获取用户信息
                        user = weixinProxy.getUser(oToken.getOpenId());
                    } else {
                        throw e;
                    }
                }
                Member member = new Member();
                BeanUtils.copyProperties(user, member, "subscribeTime");
                member.setSubscribeTime(new Date(user.getSubscribeTime() * 1000));
                session.setAttribute(SessionKeys.OAUTH_USER_KEY, memberService.upsertMember(member));
            }
        }
        return true;
    }

    private String getAccessUri(HttpServletRequest request) {
        String queryString = request.getQueryString();
        int port = request.getServerPort();
        String access_uri = String.format("%s://%s%s%s", request.getScheme(), request.getServerName(),
                request.getRequestURI(), StringUtil.isNotBlank(queryString) ? "?" + queryString : "");
        if (port != 80) {
            access_uri = String.format("%s://%s:%s%s%s", request.getScheme(), request.getServerName(), port,
                    request.getRequestURI(), StringUtil.isNotBlank(queryString) ? "?" + queryString : "");
        }
        return access_uri;
    }
}
